package Communication;

import java.io.*;
import java.util.logging.Level;
import javax.microedition.io.*;
import Command.Command;
import debuggen.*;

/**
 * BT
 * The BT info
 * @author Danny
 */
public class Bluetooth {
	// Protocol
	private String strProtocol;
	// MAC Address of bluetooth module
	private String strMacAddress;
	// Connection options
	private String strConnectionOptions;
	// Streamconnection for communication
	private StreamConnection stcConnection;
	// Reader - Read from BT
	private BufferedReader brReader;
	// Writer - Write to BT
	private BufferedWriter bwWriter;
	// Is there a connection?
	private boolean isConnected = false;
	// BT
	private static Bluetooth bt = null;
	

	/**
	 * Constructor 
	 */
	private Bluetooth()
	{
		config();
	}
	/**
	 * getInstance
	 * @return Bluetooth - the BT Connection!
	 */
	public synchronized static Bluetooth getInstance()
	{
		if(bt == null)
		{
			bt = new Bluetooth();
		}
		return bt;
	}
	
	/**
	 * config
	 * Put data in some vars.
	 */
	private void config()
	{
		// Used protocol
		strProtocol = "btspp://";
		// Mac address
		strMacAddress = "000b531320d3"; //"001E3A2CBF49"; // Address from Ricks phone
		// Connection options
		/**
		 * authenticate and encrypting data is not needed.
		 * This program is the 'slave' and the boat is the master.
		 */
		strConnectionOptions = ":01;authenticate=false;encrypt=false;master=false";
		
		
		// Check if debug mode is enabled.
		if(Debug.DEBUGGEN)
		{
			// Write bt connection string to log file.
			Debug.writeMessage("Bluetooth connection string: " 
							+ strProtocol 
							+ strMacAddress 
							+ strConnectionOptions);
		}
	}
	
	/**
	 * connect
	 * Try to connect to BT module(s).
	 * @throws DebugException 
	 * @return boolean - true if connection is ok
	 */
	public boolean connect()
	{
		// Test if we already have a connection
		if(isConnected())
		{
			// If we are already connected, return true.
			return true;
		}
		try
		{
			// Create Stream connection
			stcConnection = (StreamConnection) Connector.open(strProtocol + strMacAddress + strConnectionOptions);
			// Writer
			bwWriter = new BufferedWriter(new OutputStreamWriter(stcConnection.openOutputStream()));
			// Reader
			brReader = new BufferedReader(new InputStreamReader(stcConnection.openInputStream()));
			// isConnected = true
			isConnected = true;
			
			// Debug info
			if(Debug.DEBUGGEN)
			{
				Debug.writeMessage("Bluetooth CONNECT passed with url: " 
										+ strProtocol 
										+ strMacAddress 
										+ strConnectionOptions, 
										Level.INFO);
			}
	    }
		catch(IOException ioexc)
		{
			if(Debug.DEBUGGEN)
			{
				DebugException exc = new DebugException("PROBLEM: Connection with BT failed. ("
						+ strProtocol 
						+ strMacAddress 
						+ strConnectionOptions 
						+ ")", Level.WARNING, ioexc);
				Debug.writeMessage("Problem with bt connection", Level.WARNING, exc);
			}
			
			// Connection failed!
			return false;
		}
		// Connection ok
		return true;
	}
	/**
	 * close
	 * Close connection
	 */
	public void close()
	{
		try 
		{
			// Close reader
			brReader.close();
			// Close writer
			bwWriter.close();
			// Close stream
			stcConnection.close();
			// not connected anymore
			isConnected = false;
		}
		catch(Exception exc)
		{
			/**
			 * We can ignore this exception.
			 */
		}
	}
	/**
	 * processCommand
	 * Execute the command
	 * @param p_cmdCommand
	 */
	public void processCommand(Command p_cmdCommand)
	{
		//p_cmdCommand.execute();
		sendLine("#" + p_cmdCommand.getCommandString() + "!" + Command.EOL);
	}
	/**
	 * isConnected
	 * @return boolean - True if connected, false otherwise
	 */
	public boolean isConnected()
	{
		return isConnected;
	}
	/**
	 * sendLine
	 * Sends the command through bt
	 * @param p_strCommand
	 * @return bool - True if command is send, false otherhwise
	 */
	public boolean sendLine(String p_strCommand)
	{
		try 
		{
			// Write message!
			bwWriter.write(p_strCommand);
			// Flush connection
			bwWriter.flush();
			
			// If in debug mode, send info to log!
			if(Debug.DEBUGGEN)
			{
				// Write log message
				Debug.writeMessage("Command sending: " + p_strCommand, Level.INFO);
			}		
			// Command send! Return true
			return true;
		}catch(IOException ioexc)
		{
			// Log problem if in debug mode!
			if(Debug.DEBUGGEN)
			{
				// Write log message!
				Debug.writeMessage("Problem sending command through BT: " + p_strCommand, Level.WARNING, ioexc);
			}
			// Problem, return false!
			return false;
		}
	}
	/**
	 * readLine
	 * readChar method is preferred.
	 * @return Info readed from bt
	 */
	public String readLine()
	{
		try 
		{
			// Ready to read!
			if(brReader.ready())
			{
				// Read info from BT
				return brReader.readLine();
			} 
			else  // Not ready, so return null!
				return null;
		}catch(IOException ioexc)
		{
			// Check if we are in debug mode!
			if(Debug.DEBUGGEN)
			{
				// Write message to log
				Debug.writeMessage("Problem reading from Bluetooth.", Level.WARNING, ioexc);
			}
			// Return null if problem, or no data
			return null;
		}
	}
	/**
	 * readChar
	 * Reads char and returns int
	 * @see java.io.BufferedReader.read()
	 * @return int - see BufferedReader.read()
	 */
	public int readChar()
	{
		try
		{
			// Return readed value, or -1 if none
			return brReader.read();
		}catch(IOException ioexc)
		{
			// Check if we are in debug mode!
			if(Debug.DEBUGGEN)
			{
				// Write message to log
				Debug.writeMessage("Problem reading from Bluetooth.", Level.WARNING, ioexc);
			}
			// Return a non value: -1
			return -1;
		}
	}
}